package fri.pipt.agent.deathrow;

import java.util.concurrent.Semaphore;

import fri.pipt.agent.Agent;
import fri.pipt.protocol.Neighborhood;
import fri.pipt.protocol.Message.Direction;

public abstract class AgentAbstraction extends Agent
{
	private Object waitMutex = new Object();
	protected int stamp = -1;
	protected boolean hasFlag = false;
	protected Neighborhood neighborhood;
	protected Direction direction;
	private Pos2 position;
	private Pos2 outPos;
	private World world;
	public Direction agentMove;
	private Direction lastAgentMove;
	boolean startMoving = true;
	
	public Pos2 getPosition()
	{
		//outPos.x = position.x;
		//outPos.y = position.y;
		return new Pos2(position);//outPos;
	}
	
	public final void moveAgent(Direction where)
	{ 
		if(where == null || where == Direction.NONE)
		{
			return;
		}
		if(startMoving) //Ne premaknemo agenta če je v poteku premikanja!
		{
			startMoving = false;
			agentMove = where;
			move(where);
		}
	}
	
	
	private void scanAndWait() throws InterruptedException
	{
			scan(0);
	}
	
	@Override
	public void terminate()
	{
		//Do termination stuff!
		term();
	}

	@Override
	public void initialize()
	{
		System.out.println("Init convict...");
		position = new Pos2();
		outPos = new Pos2();
		world = new World();
		agentMove = Direction.NONE;
		init();
	}

	@Override
	public void receive(int from, byte[] message)
	{
		incommingMessage(from, message);
	}

	@Override
	public void state(int stamp, Neighborhood neighborhood,
			Direction direction, boolean hasFlag)
	{
		
		this.direction = direction;
		this.hasFlag = hasFlag;
		this.neighborhood = neighborhood;
		calcNextAgentPos();
		world.update(getPosition(), neighborhood);
		update();
		
	}

	@Override
	public void run()
	{
		while(isAlive())
		{
			try
			{
				Thread.sleep(100 + 1000/getSpeed() );
				scanAndWait();
				stamp++;
				//calculate next agent position!
				//če se agent ne pomika
				
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
	private void calcNextAgentPos()
	{
		//System.out.println("Dirrection: " + direction);
		if(direction == Direction.NONE)
		{
			if(agentMove != Direction.NONE)
			{
			
				switch (agentMove)
				{
					case DOWN:
						position.y++;
						break;
					case LEFT:
						position.x--;
						break;
					case RIGHT:
						position.x++;
						break;
					case UP:
						position.y--;
						break;

					default:
						break;
				}
				agentMoved(agentMove);
				startMoving = true; 
				agentMove = Direction.NONE;
				
			}
		}
	}
	
	
	public World getWorld() { return world; }
	
	/**
	 * Pred vsakim update se naredi scan in state update, tako da lahko v update pridobimo 
	 * Pozicijo agenta, stanje sveta okoli agenta in updejtano mapo sveta! 
	 */
	public abstract void update();
	
	/* Inicializacija kode*/
	public abstract void init();
	public abstract void term();
	public abstract void incommingMessage(int from, byte[] msg);
	
	public abstract void agentMoved( Direction dir);
//	public abstract void agentSpoted(int agentID);
}
